﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Timers;
using System.Threading;
using System.Windows.Forms;
using System.IO;

namespace GPS_Simulator
{
    public partial class Form1 : Form
    {
        string txtPath = Application.StartupPath;
        public string RxString = "", newFileName = "logfile.txt", comport_name = "comport.txt", logfile_path,
            comport_path, comport_str = "Com13", error_str = "", recommant_str = "", gpvtg = "";
        string gsa_cmd = "$GPGSA,A,3,12,21,24,22,18,15,,,,,,,2.5,1.3,2.1*3F\r\n",
            gsv1_cmd = "$GPGSV,3,1,09,18,72,248,33,24,55,036,28,12,53,137,32,22,44,305,25*79\r\n",
            gsv2_cmd = "$GPGSV,3,2,09,15,33,091,29,25,31,179,19,09,28,046,22,14,26,300,24*71\r\n",
            gsv3_cmd = "$GPGSV,3,3,09,21,13,218,20*48\r\n",
            default_data = "$GPRMC,235947.000,V,0000.0000,N,00000.0000,E,,,041299,,*1D\r\n"
                        + "$GPGGA,235947.000,0000.0000,N,00000.0000,E,0,00,0.0,0.0,M,,,,0000*00\r\n"
                        + "$GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30\r\n"
                        + "$GPGSV,1,1,01,21,00,000,*4B\r\n"
                        + "$GPVTG,,T,,M,,N,,K*4E\r\n",
            init_data = "$Kernel,v1.4.94,000004BE,19324205,F,16.367667MHz\r\n$ver,010922,rev,101208\r\n";
        char[] rmc_array, gga_array, vtg_array;
        int rmc_checksum, gga_checksum, vtg_checksum;
        int init_interval = 0, latit_hour = 0, longit_hour = 0, init_coldstart = 0, coldstart = 0, a;
        double latit_min = 0, longit_min = 0, latit_diff = 0, longit_diff = 0,
               speed_var = 0, speed_diff = 0, course_var = 0, course_diff = 0;
        Thread sendding_thread;
        public Semaphore echo_sem = new Semaphore(1, 1), access_sem = new Semaphore(1, 1);
        public Semaphore sendding_sem = new Semaphore(0, 1), disconnect_sem = new Semaphore(0, 1);
        public DateTime theDate;
        public bool disconnect_flag = false;
        public Form1()
        {
            InitializeComponent();
        }

        private void checkBox7_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen == false)
            {
                try
                {
                    StreamReader file = System.IO.File.OpenText(comport_path);
                    serialPort1.PortName = file.ReadLine();
                    serialPort1.BaudRate = Convert.ToInt32(file.ReadLine());
                    serialPort1.DataBits = Convert.ToInt32(file.ReadLine());

                    serialPort1.Encoding = Encoding.GetEncoding(28591);
                    switch (file.ReadLine())
                    {
                        case "0":
                            serialPort1.StopBits = System.IO.Ports.StopBits.None;
                            break;
                        case "1":
                            serialPort1.StopBits = System.IO.Ports.StopBits.One;
                            break;
                        case "1.5":
                            serialPort1.StopBits = System.IO.Ports.StopBits.OnePointFive;
                            break;
                        case "2":
                            serialPort1.StopBits = System.IO.Ports.StopBits.Two;
                            break;
                        default:
                            break;
                    } switch (file.ReadLine())
                    {
                        case "None":
                            serialPort1.Parity = System.IO.Ports.Parity.None;
                            break;
                        case "Even":
                            serialPort1.Parity = System.IO.Ports.Parity.Even;
                            break;
                        case "Old":
                            serialPort1.Parity = System.IO.Ports.Parity.Odd;
                            break;
                        default:
                            break;
                    }
                    serialPort1.Handshake = System.IO.Ports.Handshake.None;
                    serialPort1.ReadTimeout = 4000;
                    serialPort1.WriteTimeout = 4000;
                    serialPort1.Open();

                }
                catch
                {
                    comport comport_form = new comport(this);
                    comport_form.ShowDialog();
                    return;
                }

            }
            access_sem.WaitOne();
            System.IO.File.AppendAllText(logfile_path, "__________" + DateTime.Now.ToLongTimeString()
                                        + ": Connect __________\r\n");
            serialPort1.Write(init_data.Substring(0, 10));
            richTextBox1.AppendText(init_data.Substring(0, 10));
            System.IO.File.AppendAllText(logfile_path, "__________" + DateTime.Now.ToLongTimeString()
                                            + ": send data __________\r\n"
                                            + init_data.Substring(0, 10));
            //for disconnect
            if (radioButton3.Checked)
            {
                serialPort1.Close();
                System.IO.File.AppendAllText(logfile_path, "\r\n__________" + DateTime.Now.ToLongTimeString()
                                            + ": Disconnect 2 __________\r\n");
                richTextBox1.AppendText("\r\n");
                access_sem.Release();
                return;
            }


            serialPort1.Write(init_data.Substring(10, init_data.Length - 10));
            richTextBox1.AppendText(init_data.Substring(10, init_data.Length - 10));
            System.IO.File.AppendAllText(logfile_path, DateTime.Now.ToLongTimeString() + ":"
                                            + init_data.Substring(10, init_data.Length - 10));
            if (radioButton2.Checked)
            {
                serialPort1.Close();
                System.IO.File.AppendAllText(logfile_path, "__________" + DateTime.Now.ToLongTimeString()
                                            + ": Disconnect 1 __________\r\n");
                access_sem.Release();
                return;
            }
            timer1.Enabled = true;
            button1.Enabled = false;
            button2.Enabled = false;
            button6.Enabled = false;
            access_sem.Release();

        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            System.Diagnostics.Process MY = System.Diagnostics.Process.GetCurrentProcess();
            MY.PriorityClass = System.Diagnostics.ProcessPriorityClass.High;
            logfile_path = System.IO.Path.Combine(txtPath, newFileName);
            comport_path = System.IO.Path.Combine(txtPath, comport_name);
            comboBox3.SelectedIndex = 0;
            comboBox5.SelectedIndex = 0;
            System.IO.File.WriteAllText(logfile_path, "");
            string[] theSerialPortNames = System.IO.Ports.SerialPort.GetPortNames();
            if (System.IO.File.Exists(comport_path))
            {
                comport_str = System.IO.File.ReadAllText(comport_path);
            }
            else
            {
                comport comport_form = new comport(this);
                comport_form.ShowDialog();
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                theDate = new DateTime(2000 + Convert.ToInt32(textBox6.Text.Substring(4, 2)),
                                        Convert.ToInt32(textBox6.Text.Substring(2, 2)),
                                        Convert.ToInt32(textBox6.Text.Substring(0, 2))
                                        );
            }
            catch
            {
                textBox6.ForeColor = Color.Red;
                return;
            }
            try
            {
                theDate = new DateTime(2000 + Convert.ToInt32(textBox6.Text.Substring(4, 2)),
                                        Convert.ToInt32(textBox6.Text.Substring(2, 2)),
                                        Convert.ToInt32(textBox6.Text.Substring(0, 2)),
                                        Convert.ToInt32(textBox17.Text.Substring(0, 2)),
                                        Convert.ToInt32(textBox17.Text.Substring(2, 2)),
                                        Convert.ToInt32(textBox17.Text.Substring(4, 2)),
                                        Convert.ToInt32(textBox16.Text)
                                        );
            }
            catch
            {
                textBox17.ForeColor = Color.Red;
                return;
            }
            init_interval = (int)numericUpDown14.Value * 10;
            init_coldstart = (int)numericUpDown9.Value * 10;
            coldstart = 0;
            timer1.Interval = (int)numericUpDown14.Value * 10;
            latit_min = Convert.ToDouble(textBox8.Text) + Convert.ToDouble(textBox11.Text) / 10000;
            longit_min = Convert.ToDouble(textBox9.Text) + Convert.ToDouble(textBox12.Text) / 10000;
            speed_var = Convert.ToDouble(textBox15.Text) + Convert.ToDouble(textBox5.Text) / 10;
            course_var = Convert.ToDouble(textBox7.Text) + Convert.ToDouble(textBox10.Text) / 10;
            try
            {
                latit_diff = Convert.ToDouble(textBox13.Text);
            }
            catch
            {
                textBox13.ForeColor = Color.Red;
                return;
            }
            try
            {
                longit_diff = Convert.ToDouble(textBox14.Text);
            }
            catch
            {
                textBox14.ForeColor = Color.Red;
                return;
            }
            try
            {
                speed_diff = Convert.ToDouble(textBox19.Text);
            }
            catch
            {
                textBox19.ForeColor = Color.Red;
                return;
            }
            try
            {
                course_diff = Convert.ToDouble(textBox18.Text);
            }
            catch
            {
                textBox18.ForeColor = Color.Red;
                return;
            }
        }

        public void start_timer(object sender, EventArgs e)
        {
            timer1.Start();
        }

        public void stop_timer(object sender, EventArgs e)
        {
            timer1.Stop();
        }
        public void sendding_funtion()
        {
            try
            {
                access_sem.WaitOne();
                if (coldstart <= init_coldstart)
                {
                    this.Invoke((MethodInvoker)delegate()
                    {
                        coldstart += init_interval;
                        serialPort1.Write(default_data);
                        richTextBox1.AppendText(default_data);
                        System.IO.File.AppendAllText(logfile_path, "__________" + DateTime.Now.ToLongTimeString() + ": send data __________\r\n"
                                                        + default_data);

                    });
                }
                else
                {
                    this.Invoke((MethodInvoker)delegate()
                    {
                        string gprmc = "GPRMC," + theDate.ToString("HHmmss.fff") + "," + comboBox3.Text + ","
                                        + latit_min.ToString("#,0000.0000").Replace(",", "") + ",N,"
                                        + longit_min.ToString("#,00000.0000").Replace(",", "")
                                        + ",E," + speed_var.ToString("#,000.0").Replace(",", "")
                                        + "," + course_var.ToString("#,000.0").Replace(",", "")
                                        + "," + theDate.ToString("ddMMyy") + ",,,A";
                        textBox6.Text = theDate.ToString("ddMMyy");
                        textBox17.Text = theDate.ToString("HHmmss");
                        textBox16.Text = theDate.ToString("fff");
                        string gpgga = "GPGGA," + theDate.ToString("HHmmss.fff") + ","
                                        + latit_min.ToString("#,0000.0000").Replace(",", "") + ",N,"
                                        + longit_min.ToString("#,00000.0000").Replace(",", "")
                                        + ",E," + "1," + comboBox5.Text + ",1.3,67.1,M,37.2,M,,0000";
                        gpvtg = "GPVTG," + course_var.ToString("#,000.0").Replace(",", "")
                                        + ",T,,M," + (speed_var * 0.539957).ToString("#,000.0").Replace(",", "")
                                        + ",N," + speed_var.ToString("#,000.0").Replace(",", "") + ",K,";
                        textBox15.Text = speed_var.ToString("#,000.0").Substring(0, speed_var.ToString("#,000.000").IndexOf("."));
                        textBox5.Text = speed_var.ToString("#,000.0").Substring(speed_var.ToString("#,000.000").IndexOf(".") + 1, 1);
                        textBox7.Text = course_var.ToString("#,000.0").Substring(0, course_var.ToString("#,000.000").IndexOf("."));
                        textBox10.Text = course_var.ToString("#,000.0").Substring(course_var.ToString("#,000.000").IndexOf(".") + 1, 1);
                        textBox8.Text = latit_min.ToString("#,0000").Replace(",", "");
                        textBox11.Text = latit_min.ToString("#,000.0000").Substring(latit_min.ToString("#,000.0000").IndexOf(".") + 1, 4);
                        textBox9.Text = longit_min.ToString("#,00000").Replace(",", "");
                        textBox12.Text = longit_min.ToString("#,00000.0000").Substring(longit_min.ToString("#,000.0000").IndexOf(".") + 1, 4);

                        rmc_array = gprmc.ToArray();
                        rmc_checksum = rmc_array[0];
                        foreach (char port in rmc_array)
                        {
                            rmc_checksum ^= port;
                            a = port;
                        }
                        rmc_checksum ^= rmc_array[0];
                        gprmc = "$" + gprmc + "*" + rmc_checksum.ToString("x2").ToUpper() + "\r\n";
                        gga_array = gpgga.ToArray();
                        gga_checksum = gga_array[0];
                        foreach (char port in gga_array)
                        {
                            gga_checksum ^= port;
                        }
                        gga_checksum ^= gga_array[0];
                        gpgga = "$" + gpgga + "*" + gga_checksum.ToString("x2").ToUpper() + "\r\n";
                        vtg_array = gpvtg.ToArray();
                        vtg_checksum = vtg_array[0];
                        foreach (char port in vtg_array)
                        {
                            vtg_checksum ^= port;
                        }
                        vtg_checksum ^= vtg_array[0];
                        gpvtg = "$" + gpvtg + "*" + vtg_checksum.ToString("x2").ToUpper() + "\r\n";
                        System.IO.File.AppendAllText(logfile_path, "__________" + DateTime.Now.ToLongTimeString()
                                                        + ": send data __________\r\n");
                        System.IO.File.AppendAllText(logfile_path, gprmc);
                        richTextBox1.AppendText(gprmc);
                        serialPort1.Write(gprmc);
                        System.IO.File.AppendAllText(logfile_path, gpgga);
                        richTextBox1.AppendText(gpgga);
                        serialPort1.Write(gpgga);
                        System.IO.File.AppendAllText(logfile_path, gsa_cmd + gsv1_cmd + gsv2_cmd + gsv3_cmd);
                        richTextBox1.AppendText(gsa_cmd + gsv1_cmd + gsv2_cmd + gsv3_cmd);
                        serialPort1.Write(gsa_cmd + gsv1_cmd + gsv2_cmd + gsv3_cmd);
                    });

                    if (radioButton3.Checked)
                    {
                        serialPort1.Close();
                        System.IO.File.AppendAllText(logfile_path, "\r\n__________" + DateTime.Now.ToLongTimeString()
                                                    + ": Disconnect 2 __________\r\n");
                        this.Invoke((MethodInvoker)delegate()
                        {
                            richTextBox1.AppendText("\r\n");
                        });
                        timer1.Enabled = false;
                        disconnect_flag = true;
                        disconnect_sem.WaitOne();
                        serialPort1.Open();
                        timer1.Enabled = true;
                        disconnect_flag = false;
                    }
                    this.Invoke((MethodInvoker)delegate()
                    {
                        System.IO.File.AppendAllText(logfile_path, gpvtg);
                        richTextBox1.AppendText(gpvtg);
                        serialPort1.Write(gpvtg);
                        theDate = theDate.AddMilliseconds(init_interval);
                        latit_min = (latit_min + latit_diff) % 9000;
                        if (latit_min < 0)
                            latit_min = latit_min + 9000;
                        longit_min = (longit_min + longit_diff) % 18000;
                        if (longit_min < 0)
                            longit_min = longit_min + 18000;
                        course_var = (course_var + course_diff) % 360;
                        if (course_var < 0)
                            course_var = course_var + 360;
                        speed_var = (speed_var + speed_diff) % 360;
                        if (speed_var < 0)
                            speed_var = speed_var + 359;
                    });

                    if (radioButton2.Checked)
                    {
                        serialPort1.Close();
                        System.IO.File.AppendAllText(logfile_path, "\r\n__________" + DateTime.Now.ToLongTimeString()
                                                    + ": Disconnect 1 __________\r\n");
                        this.Invoke((MethodInvoker)delegate()
                        {
                            richTextBox1.AppendText("\r\n");
                        });
                        timer1.Enabled = false;
                        disconnect_flag = true;
                        disconnect_sem.WaitOne();
                        serialPort1.Open();
                        timer1.Enabled = true;
                        disconnect_flag = false;
                    }
                }
                access_sem.Release();

            }
            catch (ThreadInterruptedException)
            {
                return;
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            timer1.Stop();
            button1.Enabled = true;
            button2.Enabled = true;
            button6.Enabled = true;
            radioButton1.Enabled = true;
            radioButton2.Enabled = true;
            radioButton3.Enabled = true;
            //serialPort1.Write("$PSRF103,00,01,00,01*25\r\n");
            // for (int i = 0; i < 0x7fffffff; i++)
            //    textBox1.Text += "000000000000000000\r\n";
        }

        private void numericUpDown7_ValueChanged(object sender, EventArgs e)
        {

        }
        private void Form_Closed(object sender, EventArgs e)
        {
            try
            {
                sendding_thread.Interrupt();
            }
            catch { }
        }

        private void richTextBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void button6_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void button7_Click(object sender, EventArgs e)
        {
            openFileDialog1.ShowDialog();
            comboBox6.Text = openFileDialog1.FileName;
            access_sem.WaitOne();
            if (System.IO.File.Exists(comboBox6.Text))
            {
                try
                {

                    StreamReader file = System.IO.File.OpenText(comboBox6.Text);
                    numericUpDown9.Value = Convert.ToDecimal(file.ReadLine());
                    numericUpDown14.Value = Convert.ToDecimal(file.ReadLine());
                    comboBox3.Text = file.ReadLine();
                    textBox6.Text = file.ReadLine();
                    textBox17.Text = file.ReadLine();
                    textBox16.Text = file.ReadLine();
                    textBox8.Text = file.ReadLine();
                    textBox11.Text = file.ReadLine();
                    textBox13.Text = file.ReadLine();
                    textBox9.Text = file.ReadLine();
                    textBox12.Text = file.ReadLine();
                    textBox14.Text = file.ReadLine();
                    comboBox5.Text = file.ReadLine();
                    textBox7.Text = file.ReadLine();
                    textBox10.Text = file.ReadLine();
                    textBox18.Text = file.ReadLine();
                    textBox15.Text = file.ReadLine();
                    textBox5.Text = file.ReadLine();
                    textBox19.Text = file.ReadLine();
                    file.Close();
                }
                catch { }
            }
            access_sem.Release();
        }

        private void textBox6_TextChanged(object sender, EventArgs e)
        {

        }

        private void textBox6_KeyPress(object sender, KeyPressEventArgs e)
        {

            if (!Char.IsDigit(e.KeyChar) && !Char.IsControl(e.KeyChar))
            {
                e.Handled = true;
            }
        }

        private void textBox6_Leave(object sender, EventArgs e)
        {
            Control control = (Control)sender;
            control.ForeColor = Color.Black;
            if (control.Text.Length == 0)
            {
                control.Text = "000000";
            }
            else
            {
                control.Text = (int.Parse(control.Text, System.Globalization.NumberStyles.Integer)).ToString("d6");
            }
        }

        private void textBox16_Leave(object sender, EventArgs e)
        {
            Control control = (Control)sender;
            if (control.Text.Length == 0)
                control.Text = "000";
            else
            {
                control.Text = (int.Parse(control.Text, System.Globalization.NumberStyles.Integer)).ToString("d3");
            }
        }

        private void textBox8_Leave(object sender, EventArgs e)
        {
            Control control = (Control)sender;
            if (control.Text.Length == 0)
                control.Text = "0000";
            else
            {
                control.Text = (int.Parse(control.Text, System.Globalization.NumberStyles.Integer)).ToString("d4");
            }
        }

        private void textBox9_Leave(object sender, EventArgs e)
        {
            Control control = (Control)sender;
            if (control.Text.Length == 0)
                control.Text = "00000";
            else
            {
                control.Text = (int.Parse(control.Text, System.Globalization.NumberStyles.Integer)).ToString("d5");
            }
        }

        private void textBox10_Leave(object sender, EventArgs e)
        {
            Control control = (Control)sender;
            if (control.Text.Length == 0)
                control.Text = "0";
            else
            {
                control.Text = (int.Parse(control.Text, System.Globalization.NumberStyles.Integer)).ToString("d1");
            }
        }

        private void textBox6_Leave_1(object sender, EventArgs e)
        {
            Control control = (Control)sender;
            control.ForeColor = Color.Black;
            if (control.Text.Length == 0)
                control.Text = "000000";
            else
            {
                control.Text = (int.Parse(control.Text, System.Globalization.NumberStyles.Integer)).ToString("d6");
            }
        }


        private void textBox6_Leave_2(object sender, EventArgs e)
        {
            Control control = (Control)sender;
            control.ForeColor = Color.Black;
            if (control.Text.Length == 0)
                control.Text = "0000";
        }

        private void timer1_Elapsed(object sender, ElapsedEventArgs e)
        {
            sendding_thread = new Thread(sendding_funtion);
            sendding_thread.Start();
        }

        private void button9_Click(object sender, EventArgs e)
        {
            openFileDialog1.ShowDialog();
            comboBox6.Text = openFileDialog1.FileName;
            if (System.IO.File.Exists(comboBox6.Text))
            {
                access_sem.WaitOne();
                try
                {
                    string[] form_init = {numericUpDown9.Value.ToString(), numericUpDown14.Value.ToString() ,
                                comboBox3.Text,textBox6.Text ,textBox17.Text , textBox16.Text , textBox8.Text
                                , textBox11.Text , textBox13.Text , textBox9.Text , textBox12.Text , textBox14.Text
                                , comboBox5.Text , textBox7.Text , textBox10.Text , textBox18.Text , textBox15.Text
                                , textBox5.Text , textBox19.Text};
                    System.IO.File.WriteAllLines(comboBox6.Text, form_init);
                }
                catch
                {
                    access_sem.WaitOne();
                    access_sem.Release();
                }
                access_sem.Release();

            }
        }

        private void textBox17_TextChanged(object sender, EventArgs e)
        {

        }

        private void button4_Click(object sender, EventArgs e)
        {
            double i = 1 + Convert.ToDouble(textBox13.Text);
            richTextBox1.AppendText(i.ToString());
        }

        private void radioButton1_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButton1.Checked == true)
            {
                if (disconnect_flag)
                {
                    sendding_thread.Interrupt();
                    serialPort1.Open();
                    disconnect_flag = false;
                    timer1.Enabled = true;
                    access_sem.Release();
                    disconnect_sem.Release();
                }
            }
        }

        private void radioButton4_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButton4.Checked == true)
            {
                if (disconnect_flag)
                {
                    disconnect_sem.Release();
                }
            }

        }
        public int year = 2000, month = 1, date = 1, hour = 0;
        private void jp_utc_convert()
        {
            if (hour < 15)
            {
                hour += 9;
            }
            else if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
            {
                hour = (hour + 9) % 24;
                date++;
                if (date > 31)
                {
                    date = 1;
                    month++;
                    if (month > 12)
                    {
                        month = 1;
                        year++;
                    }
                }
            }
            else if (month == 4 || month == 6 || month == 9 || month == 11)
            {
                hour = (hour + 9) % 24;
                date++;
                if (date > 30)
                {
                    date = 1;
                    month++;
                }
            }
            else
            {
                hour = (hour + 9) % 24;
                date++;
                if (date > 28)
                {
                    if (((year % 400) == 0) || ((year % 100 != 0) && (year % 4 == 0)))
                    {
                    }
                    else
                    {
                        date = 1;
                        month++;
                    }
                }
            }
        }

        private void textBox7_Leave(object sender, EventArgs e)
        {

            Control control = (Control)sender;
            control.ForeColor = Color.Black;
            if (control.Text.Length == 0)
                control.Text = "000";
            else if ((int.Parse(control.Text, System.Globalization.NumberStyles.Integer)) >= 360)
            {
                control.ForeColor = Color.Red;
            }
            else
            {
                control.Text = (int.Parse(control.Text, System.Globalization.NumberStyles.Integer)).ToString("d3");
            }
        }

        private void numericUpDown14_ValueChanged(object sender, EventArgs e)
        {

        }
    }
}
